bitkeeper revision 1.1357 (4267c91c8u7H5ttS9RWRyBY5FrTm3g)
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 21 Apr 2005 15:39:08 +0000 (15:39 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 21 Apr 2005 15:39:08 +0000 (15:39 +0000)
Fix APIC setup on legacy systems.
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/apic.c
xen/arch/x86/setup.c

index e00e403f35d17a0bc76f0bf7f129b0f1446bd600..f3b5c64f77c08d683edf1bc39b853f8a88cf8873 100644 (file)
@@ -229,17 +229,48 @@ void __init sync_Arb_IDs(void)
 
 extern void __error_in_apic_c (void);
 
-/*
- * WAS: An initial setup of the virtual wire mode.
- * NOW: We don't bother doing anything. All we need at this point
- * is to receive timer ticks, so that 'jiffies' is incremented.
- * If we're SMP, then we can assume BIOS did setup for us.
- * If we're UP, then the APIC should be disabled (it is at reset).
- * If we're UP and APIC is enabled, then BIOS is clever and has 
- * probably done initial interrupt routing for us.
- */
 void __init init_bsp_APIC(void)
 {
+    unsigned long value, ver;
+
+    /*
+     * Don't do the setup now if we have a SMP BIOS as the through-I/O-APIC 
+     * virtual wire mode might be active.
+     */
+    if (smp_found_config || !cpu_has_apic)
+        return;
+
+    value = apic_read(APIC_LVR);
+    ver = GET_APIC_VERSION(value);
+    
+    /*
+     * Do not trust the local APIC being empty at bootup.
+     */
+    clear_local_APIC();
+    
+    /*
+     * Enable APIC.
+     */
+    value = apic_read(APIC_SPIV);
+    value &= ~APIC_VECTOR_MASK;
+    value |= APIC_SPIV_APIC_ENABLED;
+    
+    /* This bit is reserved on P4/Xeon and should be cleared */
+    if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 == 15))
+        value &= ~APIC_SPIV_FOCUS_DISABLED;
+    else
+        value |= APIC_SPIV_FOCUS_DISABLED;
+    value |= SPURIOUS_APIC_VECTOR;
+    apic_write_around(APIC_SPIV, value);
+
+    /*
+     * Set up the virtual wire mode.
+     */
+    apic_write_around(APIC_LVT0, APIC_DM_EXTINT);
+    value = APIC_DM_NMI;
+    if (!APIC_INTEGRATED(ver))              /* 82489DX */
+        value |= APIC_LVT_LEVEL_TRIGGER;
+    apic_write_around(APIC_LVT1, value);
 }
 
 void __init setup_local_APIC (void)
index e42b319fc4519648c8a5bcdf9941c4ebc91b4900..8b8f8182e0f9690ceac5559f18bbbdabee65c460 100644 (file)
@@ -388,11 +388,11 @@ static void __init start_of_day(void)
     if ( smp_found_config ) 
         get_smp_config();
 #endif
+    init_apic_mappings(); /* make APICs addressable in our pagetables. */
     scheduler_init();  
     init_IRQ();  /* installs simple interrupt wrappers. Starts HZ clock. */
     trap_init();
     time_init(); /* installs software handler for HZ clock. */
-    init_apic_mappings(); /* make APICs addressable in our pagetables. */
 
     arch_init_memory();